/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bungabungaball.player;

import bungabungaball.GlobalSettings;
import bungabungaball.PlayerControl;
import com.esotericsoftware.kryonet.Server;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.World;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;

/**
 * A Player that is controlled by CPU
 * 
 * @author Ingo Klose, Stephan Meyer, Sebastian Lehmann
 * @version 1.0
 */
public class CPU extends Player {

    
    /**
     * The server
     */
    public static Server server;
    /**
     * Checks if the player transfixes in a corner
     */
    public boolean cornerState = false;
    /**
     * Player´s skill
     */
    public float skillWendigkeit = GlobalSettings.skill;

    /**
     * Constructor
     * @param x
     * @param y
     * @param image
     * @param w
     */
    public CPU(int x, int y, Image image, World w) {
        super(x, y, image, w);
        init();
    }

    /**
     * Constructor
     * @param x
     * @param y
     * @param image
     */
    public CPU(int x, int y, Image image) {
        super(x, y, image);
        init();
    }

    /**
     * Constructor
     * @param x
     * @param y
     */
    public CPU(int x, int y) {
        super(x, y);
        init();
    }

    /**
     * Constructor
     * @param image
     */
    public CPU(Image image) {
        super(image);
        init();
    }

    /**
     * Draw the player
     * @param g
     */
    @Override
    public void draw(Graphics g) {
        g.drawImage(image, x, y);
    }


    /**
     * Player will be moved
     * 
     * @param body
     * @param delta
     */
    private void go(Body body, int delta) {

        float hip = this.speed * delta;
        double speedRotation = Math.toRadians(this.getRotation() - 90.f);
        Vec2 force = new Vec2((float) (hip * Math.cos(speedRotation)), (float) (hip * Math.sin(speedRotation)));
        
        if (controlMode == GlobalSettings.ControlMode.Normal) {
            body.setLinearVelocity(force);
        } else {
            body.applyLinearImpulse(force, body.getWorldCenter());
        }
    }

 
     /**
     * Player goes back
     * 
     * @param body
     * @param delta
     */
    private void goBack(Body body, int delta) {

        float hip = this.speed * delta;
        double speedRotation = Math.toRadians(this.getRotation() - 90.f);
        Vec2 force = new Vec2(-(float) (hip * Math.cos(speedRotation)), -(float) (hip * Math.sin(speedRotation)));
        
        if (controlMode == GlobalSettings.ControlMode.Normal) {
            body.setLinearVelocity(force);
        } else {
            body.applyLinearImpulse(force, body.getWorldCenter());
        }
    }

         /**
     * If the player is transfixed in a corner, the variable cornerState will be set.
     * 
     * @param body
     * @param delta
     */
    private void proofCornerPosition(double playerX, double playerY, double mittelpunktX, double mittelpunktY, double sizex, double sizey, double ballX, double ballY) {

        double eckeLinksObenX = (mittelpunktX - (sizex / 2) - 12);
        double eckeLinksUntenX = (mittelpunktX - (sizex / 2) - 12);
        double eckeRechtsObenX = (mittelpunktX + (sizex / 2) + 12);
        double eckeRechtsUntenX = (mittelpunktX + (sizex / 2) + 12);
        double eckeLinksObenY = mittelpunktY - (sizey / 2) - 12;
        double eckeLinksUntenY = mittelpunktY + (sizey / 2) - 12;
        double eckeRechtsObenY = mittelpunktY - (sizey / 2) - 12;
        double eckeRechtsUntenY = mittelpunktY + (sizey / 2) - 12;
        double beta = 0;
        double alpha = 0;

        //Ecke links unten
        if (playerX < (eckeLinksUntenX + 45) && playerY > (eckeLinksUntenY - 45) && ballX < (eckeLinksUntenX + 45) && ballY < (eckeLinksUntenY - 45)) {
            cornerState = true;
        }
        //Ecke links oben
        if (playerX < (eckeLinksObenX + 65) && playerY > (eckeLinksObenY + 30) && ballX < (eckeLinksObenX + 30) && ballY < (eckeLinksObenY + 30)) {
            cornerState = true;
        }
        //Ecke rechts unten
        if (playerX > (eckeRechtsUntenX - 65) && playerY > (eckeRechtsUntenY - 65) && ballX > (eckeRechtsUntenX - 65) && ballY > (eckeRechtsUntenY - 65)) {
            cornerState = true;
        }
        //Ecke rechts oben
        if (playerX > (eckeRechtsObenX - 65) && playerY < (eckeRechtsObenY + 65) && ballX > (eckeRechtsObenX - 65) && ballY < (eckeRechtsObenY + 65)) {
            cornerState = true;
        }

    }

    /**
     *
     * Calculates the next step of the Player
     * 
     * @param pc
     * @param delta
     * @param body
     * @param keyMapClientPlayer
     * 
     */
    @Override
    public void move(PlayerControl pc, int delta, Body body, boolean[] keyMapClientPlayer) {

        double alphaRev = 0;
        double alpha = 0;
        double richtung = this.getRichtung();
        if (richtung < 0) {
            richtung += 360;
        }
        double beta = 0;
        double playerX = this.x;
        double playerY = this.y;
        double ballX = pc.ballPositionX;
        double ballY = pc.ballPositionY;
        ballX += 20;
        ballY -= 20;
        double mittelpunktX = pc.mittelpunktX;
        double mittelpunktY = pc.mittelpunktY;
        double fieldSizeX = pc.fieldSzX;
        double fieldSizeY = pc.fieldSzY;
        boolean bewegt = false;


        //Fall Eckenabhandlung

        this.proofCornerPosition(playerX, playerY, mittelpunktX, mittelpunktY, fieldSizeX, fieldSizeY, ballX, ballY);

        if (cornerState) {

            beta = ((fieldSizeY / 2) / (fieldSizeX));
            alpha = Math.abs(Math.toDegrees(Math.atan(beta)));
            if (richtung < alpha) {
                this.rotate(-skillWendigkeit);
            }
            if (richtung > alpha) {
                this.rotate(skillWendigkeit);
            }
            this.goBack(body, delta);


            if (playerX > (mittelpunktX - (fieldSizeX / 2)) && playerY > (mittelpunktY - 100) && playerY < (mittelpunktY + 100)) {
                cornerState = false;
            }
            return;
        }

        // Fall 1
        if (playerX > ballX && playerY < ballY && playerY < mittelpunktY) {
            ballX -= 10;
            ballY -= 20;
            beta = ((playerX - ballX) / (ballY - playerY));
            alpha = Math.abs(Math.toDegrees(Math.atan(beta)));
            alphaRev = 180 + alpha;
            if (richtung < alpha || richtung > alphaRev) {
                // drehe nach links
                this.rotate(-skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }
            if (richtung < alphaRev && richtung > alpha) {
                // drehe nach rechts
                this.rotate(skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }

        }

        // Fall 2
        if (playerX > ballX && playerY > ballY && playerY < mittelpunktY) {

            ballX -= 10;
            ballY -= 20;
            beta = ((playerX - ballX) / (playerY - ballY));
            alpha = Math.abs(Math.toDegrees(Math.atan(beta)));
            alphaRev = 180 - alpha;

            if (richtung > alphaRev && richtung < (360 - alpha)) {
                // drehe nach rechts
                this.rotate(skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }
            if (richtung > (360 - alpha) || richtung < alphaRev) {
                // drehe nach links
                this.rotate(-skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }

        }
        // Fall 3
        if (playerX > ballX && playerY < ballY && playerY > mittelpunktY) {

            ballX -= 10;
            beta = ((playerX - ballX) / (ballY - playerY));
            alpha = Math.abs(Math.toDegrees(Math.atan(beta)));
            alphaRev = 180 + alpha;

            if (richtung < alphaRev && richtung > alpha) {
                // drehe nach rechts
                this.rotate(skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }
            if (richtung < alpha || richtung > alphaRev) {
                // drehe nach links
                this.rotate(-skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }

        }
        // Fall 4
        if (playerX > ballX && playerY > ballY && playerY > mittelpunktY) {

            ballX -= 10;
            beta = ((playerX - ballX) / (playerY - ballY));
            alpha = Math.abs(Math.toDegrees(Math.atan(beta)));
            alphaRev = 180 - alpha;

            if (richtung > alphaRev) {
                // drehe nach rechts
                this.rotate(skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }
            if (richtung < alphaRev || richtung > (360 - alpha)) {
                // drehe nach links
                this.rotate(-skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }

        }
        // Fall 5
        if (playerX < ballX && playerY < ballY && playerY < mittelpunktY) {

            beta = ((ballY - playerY) / (ballX - playerX));
            alpha = 90 + Math.abs((Math.toDegrees(Math.atan(beta)) / 2));
            alphaRev = alpha - 90;

            if (richtung < alpha || richtung > (360 - alphaRev)) {
                // drehe nach rechts
                this.rotate(skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }
            if (richtung > alpha && richtung < (360 - alphaRev)) {
                // drehe nach links
                this.rotate(-skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }

        }
        // Fall 6
        if (playerX < ballX && playerY > ballY && playerY < mittelpunktY) {

            beta = ((ballY - playerY) / (ballX - playerX));
            alpha = 90 - Math.abs(Math.toDegrees(Math.atan(beta)) / 2);
            alphaRev = Math.abs(90 - alpha);

            if (richtung < alpha || richtung > (270 - alphaRev)) {
                // drehe nach rechts
                this.rotate(skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }
            if (richtung > alpha && richtung < (270 - alphaRev)) {
                // drehe nach links
                this.rotate(-skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }

        }
        // Fall 7
        if (playerX < ballX && playerY < ballY && playerY > mittelpunktY) {

            beta = ((ballY - playerY) / (ballX - playerX));
            alpha = 90 + Math.abs(Math.toDegrees(Math.atan(beta)) / 2);
            alphaRev = Math.abs(90 - alpha);

            if (richtung > alpha && richtung < (270 + alphaRev)) {
                // drehe nach links
                this.rotate(-skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }
            if (richtung < alpha || richtung > (270 + alphaRev)) {
                // drehe nach rechts
                this.rotate(skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }

        }
        // Fall 8
        if (playerX < ballX && playerY > ballY && playerY > mittelpunktY) {

            beta = ((ballY - playerY) / (ballX - playerX));
            alpha = 90 - Math.abs(Math.toDegrees(Math.atan(beta)) / 2);
            alphaRev = Math.abs(90 - alpha);

            if (richtung > alpha && richtung < (270 - alphaRev)) {
                // drehe nach links
                this.rotate(-skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }
            if (richtung < alpha || richtung > (270 - alphaRev)) {
                // drehe nach rechts
                this.rotate(skillWendigkeit);
                // fahre vorwärts
                this.go(body, delta);
                bewegt = true;
            }

        }


        if (!bewegt) {
            // drehe nach rechts
            this.rotate(skillWendigkeit);
            // fahre vorwärts
            this.go(body, delta);
        }



    }
}
